package sg.edu.nus.iss.cerberus.engine;

import sg.edu.nus.iss.cerberus.util.CerberusConstants;


/**
 * A class is for creation of assertEquals, assertTrue, assertFalse, assertNull and assertNotNull.
 * This class takes care of primitive data types and wrapper data types for assertion.
 * 
 * @author - Lin Naing Oo(A0079983E)
 * @see ITestEngine
 * @see TestEngine
 * */

public abstract class AssertionTestEngine implements ITestEngine{

	private String abstractAssertions(String type, String name, String expected, String assertValue, String delimiter){
		if(type != "" && name != "" && expected != "" && assertValue != "" && delimiter != "")
		{
			StringBuffer buffer = new StringBuffer();
		
			//byte
			if(type.equals(CerberusConstants.PremitiveTypes.byteType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(");");
			}
			//short
			if(type.equals(CerberusConstants.PremitiveTypes.shortType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(");");
			}
			//int
			if(type.equals(CerberusConstants.PremitiveTypes.intType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(");");
			}
			//long
			else if(type.equals(CerberusConstants.PremitiveTypes.longType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(");");
			}
			//double
			else if(type.equals(CerberusConstants.PremitiveTypes.doubleType.toString())){
				if(assertValue == "assertEquals")
					buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(delimiter).append("Math.abs(").append(expected).append(" - ").append(name).append("));");
				else
					buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(");");
			}
			//float
			else if(type.equals(CerberusConstants.PremitiveTypes.floatType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(");");
			}
			//char
			else if(type.equals(CerberusConstants.PremitiveTypes.charType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(");");
			}
			//String
			else if(type.equals(CerberusConstants.PremitiveTypes.stringType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(");");
			}
			//boolean
			else if(type.equals(CerberusConstants.PremitiveTypes.booleanType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(delimiter).append(name).append(");");
			}
			//Byte
			else if(type.equals(CerberusConstants.WrapperTypes.byteType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(".byteValue()").append(delimiter).append(name).append(".byteValue());");
			}
			//Short
			else if(type.equals(CerberusConstants.WrapperTypes.shortType.toString())){
				buffer.append(assertValue).append("(").append(expected).append(".shortValue()").append(delimiter).append(name).append(".shortValue());");
			}
			//Integer
			else if(type.equals(Integer.class.getSimpleName())){
				buffer.append(assertValue).append("(").append(expected).append(".intValue()").append(delimiter).append(name).append(".intValue());");
			}
			//Long
			else if(type.equals(Long.class.getSimpleName())){
				buffer.append(assertValue).append("(").append(expected).append(".longValue()").append(delimiter).append(name).append(".longValue());");
			}
			//Double
			else if(type.equals(Double.class.getSimpleName())){
				if(assertValue == "assertEquals")
					buffer.append(assertValue).append("(").append(expected).append(".doubleValue()").append(delimiter).append(name).append(".doubleValue()").append(delimiter).append("Math.abs(").append(expected).append(" - ").append(name).append("));");
				else
					buffer.append(assertValue).append("(").append(expected).append(".doubleValue()").append(delimiter).append(name).append(".doubleValue());");
			}
			//Float
			else if(type.equals(Float.class.getSimpleName())){
				if(assertValue == "assertEquals")
					buffer.append(assertValue).append("(").append(expected).append(".floatValue()").append(delimiter).append(name).append(".floatValue()").append(delimiter).append("Math.abs(").append(expected).append(" - ").append(name).append("));");
				else
					buffer.append(assertValue).append("(").append(expected).append(".floatValue()").append(delimiter).append(name).append(".floatValue());");
			}
			//Character
			else if(type.equals(CerberusConstants.WrapperTypes.charType.toString()))
				buffer.append(assertValue).append("(").append(expected).append(".charValue()").append(delimiter).append(name).append(".charValue());");
			//Boolean
			else if(type.equals(CerberusConstants.WrapperTypes.booleanType.toString()))
				buffer.append(assertValue).append("(").append(expected).append(".booleanValue()").append(delimiter).append(name).append(".booleanValue());");
			return buffer.toString();
		}
		return null;
	}
	
	/**
	 * A method for creating of assertEquals.
	 * 
	 * @param type String value for data type
	 * @param name String value for name of actual object
	 * @param expected String value for name of expected object
	 * */
	public String assertEquals(String type, String name, String expected)
	{
		return this.abstractAssertions(type, name, expected, "assertEquals", ", ");
	}
	
	/**
	 * A method for creating of assertTrue.
	 * 
	 * @param type String value for data type
	 * @param name String value for name of actual object
	 * @param expected String value for name of expected object
	 * */
	public String assertTrue(String type, String name, String expected)
	{
		return this.abstractAssertions(type, name, expected, "assertTrue", " == ");
	}
	
	/**
	 * A method for creating of assertFalse.
	 * 
	 * @param type String value for data type
	 * @param name String value for name of actual object
	 * @param expected String value for name of expected object
	 * */
	public String assertFalse(String type, String name, String expected)
	{
		return this.abstractAssertions(type, name, expected, "assertFalse", " == ");
	}
	
	private String abstractAssertNull(String name, String assertValue){
		if(name != "" && assertValue != "")
		{
			StringBuffer buffer = new StringBuffer();
			buffer.append(assertValue).append("(").append(name).append(");");
			return buffer.toString();
		}
		return null;
	}
	
	/**
	 * A method for creating of assertNotNull.
	 * 
	 * @param name String value for name of assertNotNull object
	 * */
	public String assertNotNull(String name){
		return this.abstractAssertNull(name, "assertNotNull");
	}
	
	/**
	 * A method for creating of assertNull.
	 * 
	 * * @param name String value for name of assertNull object
	 * */
	public String assertNull(String name){
		return this.abstractAssertNull(name, "assertNull");
	}
}
